-- ----------------------------------------------------------------------------
--        File: lSerial.lua
--      Author: Aitor Pérez Iturri
--     License: GNU General Public License
--        Date: 2011-02-08
-- Modificated: 2011-02-08
-- Description:
--
-- ----------------------------------------------------------------------------
--        TODO:
--
-- ----------------------------------------------------------------------------
--   Changelog:
--
-- ----------------------------------------------------------------------------

-- Module Definition
module("lSerial", package.seeall)

-- Imports {{{
require "luarocks.require"
require "alien"
require "bit"
require "lSerialConstants"
-- }}}
-- Global Variables
Termios = nil
-- Local Variables {{{
local libc = alien.default
local bor = bit.bor
local band = bit.band
-- glibc function interfaces {{{
libc.perror:types{
    ret = "void",
    "string"
}
libc.strerror:types{
    ret = "string",
    "int"
}
libc.open:types{
    ret="int",
    "string", "int"
}
libc.close:types{
    ret = "int",
    "int"
 } -- }}}
libc.tcgetattr:types{
    ret="int",
    "int", "pointer"
}
libc.tcsetattr:types{
    ret = "int",
    "int","int", "pointer"
}
libc.cfsetispeed:types{
	ret = "int",
	"pointer", "int"
}
libc.cfsetospeed:types{
	ret = "int",
	"pointer", "int"
}
libc.cfgetispeed:types{
	ret = "int",
	"pointer"
}
libc.cfgetospeed:types{
	ret = "int",
	"pointer"
}
-- glibc struct interfaces {{{
local termios = alien.defstruct{
    {"c_iflag", "int"},
    {"c_oflag", "int"},
    {"c_cflag", "int"},
    {"c_lflag", "int"},
    {"c_line",  "char"},
    {"c_cc",    "string"},
    {"c_ispeed","int"},
    {"c_ospeed","int"},
}
Termios = termios
-- }}}
-- }}}
-- Local Functions {{{
local function get_mode (mode)
    local mode = {}
    for f in mode:gmatch(".") do
    end
end

local close = function (serialhandler)
    if libc.close(serialhandler.fd) >= 0 then
        return true
    end
    return false, libc.strerror(alien.errno())
end

local get_output_speed = function (termios)
	return cfgetospeed(termios)
end

local get_input_speed = function (serialhandler)
	return cfgetispeed(termios)
end

local set_output_speed = function (termios, speed)
	if (libc.cfsetospeed(termios, speed) >= 0) then
		return true
	end
	return false, libc.strerror(alien.errno())
end

local set_input_speed = function (termios, speed)
	if (libc.cfsetispeed(termios, speed) >= 0) then
		return true
	end
	return false, libc.strerror(alien.errno())
end

local get_attributes = function(serialhandler, termios)
    if (libc.tcgetattr(serialhandler.fd, termios) < 0) then
        return nil, libc.strerror(alien.errno())
    end
    return termios
end
--[[
set_attributes mode:
	TCSANOW
              the change occurs immediately.
    TCSADRAIN
			  the  change  occurs  after  all output written to fd has been
			  transmitted.  This function should be used when changing
			  parameters that affect output.
    TCSAFLUSH
			  the change occurs after all output written to the object referred
			  by fd has been transmitted, and all input that has been  received
			  but  not read will be discarded before the change is made.
--]]
local set_attributes = function (serialhandler, mode, termios)
	if (libc.tcsetattr(serialhandler.fd, mode, termios) < 0) then
		return nil, libc.strerror(alien.errno())
	end	
	return true
end

local to_string = function (serialhandler)
    return string.format("serialHandler[%d]", serialhandler.fd)
end

local methods = {
    close = close,
    getInputSpeed = get_input_speed,
    getOutputSpeed = get_output_speed,
    setInputSpeed = set_input_speed,
    setOutputSpeed = set_output_speed,
    getAttributes = get_attributes,
    setAttributes = set_attributes,
}
-- }}}
-- Exported Functions {{{
open = function (device, mode)
    local t = {}
    t.fd = libc.open(device, mode)
--    t.termios = termios:new()
    if (t.fd == -1) then
        return nil, libc.strerror(alien.errno())
        --return nil, "Error openning " .. device
    end
    return setmetatable(t, {
        __index=methods,
        __tostring = to_string,
    })
end
-- }}}

-- ---------------------------------------------------------------------------
-- vim:foldmethod=marker:tabstop=4
-- ---------------------------------------------------------------------------
